from fastapi import APIRouter, Depends, HTTPException
from app.db.mongo import db


router = APIRouter(prefix="/template-outline", tags=["template-outline"])


@router.get("/{template_version_code}")
async def get_outline(template_version_code: str):
    doc = await db.report_template_outline.find_one({"template_version_code": template_version_code})
    if not doc:
        raise HTTPException(status_code=404, detail="outline_not_found")
    outline = doc.get("outline", [])
    return {"template_version_code": template_version_code, "outline": outline}


def _ensure_outline(doc: dict):
    if doc is None:
        return {"outline": []}
    doc.setdefault("outline", [])
    return doc


@router.post("/{template_version_code}/sections")
async def add_section(template_version_code: str, payload: dict):
    section_no = (payload.get("section_no") or "").strip()
    section_name = (payload.get("section_name") or "").strip()
    level = int(payload.get("level") or 1)
    style = (payload.get("style") or "").strip()
    required = bool(payload.get("required") or False)
    if not section_no or not section_name or not style or level not in (1, 2, 3):
        raise HTTPException(status_code=400, detail="invalid_section")
    doc = await db.report_template_outline.find_one({"template_version_code": template_version_code})
    doc = _ensure_outline(doc)
    outline = doc.get("outline", [])
    if any(s.get("section_no") == section_no for s in outline):
        raise HTTPException(status_code=400, detail="section_no_exists")
    new_item = {
        "section_no": section_no,
        "section_name": section_name,
        "level": level,
        "style": style,
        "required": required,
    }
    outline.append(new_item)
    await db.report_template_outline.update_one(
        {"template_version_code": template_version_code},
        {"$set": {"template_version_code": template_version_code, "outline": outline}},
        upsert=True,
    )
    return {"outline": outline}


@router.put("/{template_version_code}/sections/{section_no}")
async def update_section(template_version_code: str, section_no: str, payload: dict):
    doc = await db.report_template_outline.find_one({"template_version_code": template_version_code})
    if not doc:
        raise HTTPException(status_code=404, detail="outline_not_found")
    outline = list(doc.get("outline", []))
    idx = next((i for i, s in enumerate(outline) if s.get("section_no") == section_no), None)
    if idx is None:
        raise HTTPException(status_code=404, detail="section_not_found")
    item = dict(outline[idx])
    new_no = (payload.get("section_no") or item.get("section_no") or "").strip()
    new_name = (payload.get("section_name") or item.get("section_name") or "").strip()
    new_level = int(payload.get("level") or item.get("level") or 1)
    new_style = (payload.get("style") or item.get("style") or "").strip()
    new_required = payload.get("required") if payload.get("required") is not None else item.get("required", False)
    if not new_no or not new_name or not new_style or new_level not in (1, 2, 3):
        raise HTTPException(status_code=400, detail="invalid_section")
    if new_no != section_no and any(s.get("section_no") == new_no for s in outline):
        raise HTTPException(status_code=400, detail="section_no_exists")
    old_level = item.get("level")
    old_style = item.get("style")
    # 更新当前项
    item.update({
        "section_no": new_no,
        "section_name": new_name,
        "level": new_level,
        "style": new_style,
        "required": bool(new_required),
    })
    outline[idx] = item
    # 样式联动：仅当 level 未变化且样式变化时，批量更新同 level 项的 style
    if new_level == old_level and new_style and new_style != old_style:
        outline = [
            {**s, "style": new_style} if int(s.get("level") or 0) == int(new_level) else s
            for s in outline
        ]
    await db.report_template_outline.update_one(
        {"template_version_code": template_version_code},
        {"$set": {"outline": outline}},
    )
    return item


@router.delete("/{template_version_code}/sections/{section_no}")
async def delete_section(template_version_code: str, section_no: str):
    doc = await db.report_template_outline.find_one({"template_version_code": template_version_code})
    if not doc:
        raise HTTPException(status_code=404, detail="outline_not_found")
    outline = list(doc.get("outline", []))
    target = (section_no or "").strip()
    n = [
        s for s in outline
        if (str(s.get("section_no") or "") != target)
        and (not str(s.get("section_no") or "").startswith(target + "."))
    ]
    if len(n) == len(outline):
        raise HTTPException(status_code=404, detail="section_not_found")
    await db.report_template_outline.update_one(
        {"template_version_code": template_version_code},
        {"$set": {"outline": n}},
    )
    removed_count = len(outline) - len(n)
    return {"ok": True, "removed": removed_count}


@router.patch("/{template_version_code}/sections/reorder")
async def reorder_sections(template_version_code: str, payload: dict):
    order = payload.get("order") or []
    if not isinstance(order, list) or not all(isinstance(x, str) for x in order):
        raise HTTPException(status_code=400, detail="invalid_order")
    doc = await db.report_template_outline.find_one({"template_version_code": template_version_code})
    if not doc:
        raise HTTPException(status_code=404, detail="outline_not_found")
    outline = list(doc.get("outline", []))
    by_no = {s.get("section_no"): s for s in outline}
    new_outline = [by_no[no] for no in order if no in by_no]
    # 保留未列出的项在末尾，保持原相对顺序
    leftover = [s for s in outline if s.get("section_no") not in order]
    new_outline.extend(leftover)
    await db.report_template_outline.update_one(
        {"template_version_code": template_version_code},
        {"$set": {"outline": new_outline}},
    )
    return {"outline": new_outline}